From d99ae4b6c2b7b9f1dd8d8f915fb57e584d4fa08e Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 30 Mar 2019 12:04:51 +0100 Subject: [PATCH] cross-fade: Use gtk_css_parser_consume_any() .. and gtk_css_parser_consume_function(). gtk_css_parser_consume_any() is a new function that implements the CSS spec's any combinator ||. --- gtk/gtkcssimagecrossfade.c | 95 +++++++++++++++++++++++--------------- gtk/gtkcssparser.c | 39 ++++++++++++++++ gtk/gtkcssparserprivate.h | 17 +++++++ 3 files changed, 114 insertions(+), 37 deletions(-) diff --git a/gtk/gtkcssimagecrossfade.c b/gtk/gtkcssimagecrossfade.c index cc22ecd800..080c2a2d1d 100644 --- a/gtk/gtkcssimagecrossfade.c +++ b/gtk/gtkcssimagecrossfade.c @@ -230,59 +230,80 @@ gtk_css_image_cross_fade_snapshot (GtkCssImage *image, } static gboolean -gtk_css_image_cross_fade_parse (GtkCssImage *image, - GtkCssParser *parser) +parse_progress (GtkCssParser *parser, + gpointer option_data, + gpointer user_data) { - GtkCssImageCrossFade *self = GTK_CSS_IMAGE_CROSS_FADE (image); - double progress; + double *progress = option_data; + GtkCssValue *number; + + number = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_PERCENT | GTK_CSS_POSITIVE_ONLY); + if (number == NULL) + return FALSE; + *progress = _gtk_css_number_value_get (number, 1); + _gtk_css_value_unref (number); - if (!_gtk_css_parser_try (parser, "cross-fade(", TRUE)) + if (*progress > 1.0) { - _gtk_css_parser_error (parser, "Expected 'cross-fade('"); + _gtk_css_parser_error (parser, "Percentages over 100%% are not allowed"); return FALSE; } - if (gtk_css_number_value_can_parse (parser)) - { - GtkCssValue *number; - - number = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_PERCENT | GTK_CSS_POSITIVE_ONLY); - if (number == NULL) - return FALSE; - progress = _gtk_css_number_value_get (number, 1); - _gtk_css_value_unref (number); - - if (progress > 1.0) - { - _gtk_css_parser_error (parser, "Percentages over 100%% are not allowed"); - return FALSE; - } - } - else - progress = 0.5; + return TRUE; +} - image = _gtk_css_image_new_parse (parser); - if (image == NULL) +static gboolean +parse_image (GtkCssParser *parser, + gpointer option_data, + gpointer user_data) +{ + GtkCssImage **image = option_data; + + *image = _gtk_css_image_new_parse (parser); + if (*image == NULL) return FALSE; - gtk_css_image_cross_fade_add (self, progress, image); + return TRUE; +} - if (_gtk_css_parser_try (parser, ",", TRUE)) +static guint +gtk_css_image_cross_fade_parse_arg (GtkCssParser *parser, + guint arg, + gpointer data) +{ + GtkCssImageCrossFade *self = data; + double progress = -1.0; + GtkCssImage *image = NULL; + GtkCssParseOption options[] = { - /* XXX: allow parsing colors here */ - image = _gtk_css_image_new_parse (parser); - if (image == NULL) - return FALSE; - gtk_css_image_cross_fade_add (self, 1.0 - progress, image); - } + { (void *) gtk_css_number_value_can_parse, parse_progress, &progress }, + { NULL, parse_image, &image }, + }; + + if (!gtk_css_parser_consume_any (parser, options, G_N_ELEMENTS (options), self)) + return 0; + + g_assert (image != NULL); + + /* XXX */ + if (progress < 0) + progress = 1.0 - self->total_progress; + gtk_css_image_cross_fade_add (self, progress, image); - if (!_gtk_css_parser_try (parser, ")", TRUE)) + return 1; +} + +static gboolean +gtk_css_image_cross_fade_parse (GtkCssImage *image, + GtkCssParser *parser) +{ + if (!gtk_css_parser_has_function (parser, "cross-fade")) { - _gtk_css_parser_error (parser, "Missing closing bracket"); + _gtk_css_parser_error (parser, "Expected 'cross-fade('"); return FALSE; } - return TRUE; + return gtk_css_parser_consume_function (parser, 1, G_MAXUINT, gtk_css_image_cross_fade_parse_arg, image); } static void diff --git a/gtk/gtkcssparser.c b/gtk/gtkcssparser.c index 29cb921a29..9da98a8f6f 100644 --- a/gtk/gtkcssparser.c +++ b/gtk/gtkcssparser.c @@ -1223,3 +1223,42 @@ gtk_css_parser_consume_function (GtkCssParser *self, return result; } +gsize +gtk_css_parser_consume_any (GtkCssParser *parser, + const GtkCssParseOption *options, + gsize n_options, + gpointer user_data) +{ + gsize result; + gsize i; + + g_return_val_if_fail (parser != NULL, 0); + g_return_val_if_fail (options != NULL, 0); + g_return_val_if_fail (n_options < sizeof (gsize) * 8 - 1, 0); + + result = 0; + while (result != (1 << n_options) - 1) + { + for (i = 0; i < n_options; i++) + { + if (result & (1 << i)) + continue; + if (options[i].can_parse && !options[i].can_parse (parser, options[i].data, user_data)) + continue; + if (!options[i].parse (parser, options[i].data, user_data)) + return 0; + result |= 1 << i; + break; + } + if (i == n_options) + break; + } + if (result == 0) + { + _gtk_css_parser_error (parser, "No valid value given"); + return result; + } + + return result; +} + diff --git a/gtk/gtkcssparserprivate.h b/gtk/gtkcssparserprivate.h index 019d417f16..e4b763a826 100644 --- a/gtk/gtkcssparserprivate.h +++ b/gtk/gtkcssparserprivate.h @@ -31,6 +31,19 @@ typedef void (* GtkCssParserErrorFunc) (GtkCssParser *parser, const GError *error, gpointer user_data); +typedef struct _GtkCssParseOption GtkCssParseOption; + +struct _GtkCssParseOption +{ + gboolean (* can_parse) (GtkCssParser *parser, + gpointer option_data, + gpointer user_data); + gboolean (* parse) (GtkCssParser *parser, + gpointer option_data, + gpointer user_data); + gpointer data; +}; + GtkCssParser * _gtk_css_parser_new (const char *data, GFile *file, GtkCssParserErrorFunc error_func, @@ -90,6 +103,10 @@ gboolean gtk_css_parser_consume_function (GtkCssParser *self, guint max_args, guint (* parse_func) (GtkCssParser *, guint, gpointer), gpointer data); +gsize gtk_css_parser_consume_any (GtkCssParser *parser, + const GtkCssParseOption *options, + gsize n_options, + gpointer user_data); gboolean _gtk_css_parser_has_number (GtkCssParser *parser); char * _gtk_css_parser_read_string (GtkCssParser *parser); -- 2.30.2